"""
Case Type   : 故障&可靠性测试
Case Name   : gs_om启停，主机注入故障系统文件句柄耗尽
Create At   : 2020/10/10
Owner       : @peilinqian
Description :
    1、主点注入60s句柄耗尽故障
    2、主节点上执行gs_om stop，清除故障后再次stop
    3、主点注入60s句柄耗尽故障
    4、主节点上执行gs_om start，清除故障后再次start
Expect      :
    1、主点注入60s句柄耗尽故障，成功
    2、主节点上执行gs_om stop失败，清除故障后再次stop成功
    3、主点注入60s句柄耗尽故障，成功
    4、主节点上执行gs_om start失败，清除故障后再次start成功
History     :
    Modified by @peilinqian 2021/3/10: 使用线程启动cfe工具，规避句柄满故障导致yat阻塞
    Modified by @peilinqian 2021/8/17: 故障注入线程增加等待时间 优化结果打印
    Modified by @peilinqian 2024/2/21: 优化用例删除不必要步骤
    Modified by @peilinqian 2024/7/9： 优化用例，增加清理等待时间
    Modified by @peilinqian 2024/8/12： 优化用例，注入故障stop可能会出现stop成功打印信息。删除断言
"""
import os
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node


class ModifyConnection(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH(self.nodes[0])
        self.sta_1_sh = CommonSH(self.nodes[1])
        self.pri_root = Node(node="PrimaryRoot")
        self.constant = Constant()
        self.com = Common()
        self.inject_time = 60
        self.inject_cmd = f"rfile_deplenish (timeout) values " \
                          f"({self.inject_time})"
        self.check_cmd = "df -h"

    def test_main(self):
        step_txt = '----step1:主点注入60s句柄耗尽故障; expect:成功----'
        self.log.info(step_txt)
        session = ComThread(self.com.cfe_inject,
                            args=(self.pri_root,
                                  self.inject_cmd))
        session.setDaemon(True)
        session.start()
        self.start_time = time.time()

        self.log.info("----step2:主节点上执行gs_om stop  expect:失败----")
        result = self.pri_sh.stopDbCluster(get_detail=True)
        self.log.info(result)
        self.assertIn(self.constant.TOO_MANYY_FILE_MSG, result,
                      "执行失败" + step_txt)

        self.log.info("-----注入故障结果-----")
        session.join(60)
        result = session.get_result()
        self.log.info(result)
        self.assertIn(self.constant.SUCCESS_CFE_FULL_FILENUM_MSG, result,
                      "执行失败" + step_txt)
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.pri_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                break

        self.log.info("----step2:故障清理后主节点上执行gs_om stop expect：成功----")
        result = self.pri_sh.stopDbCluster(get_detail=True)
        self.log.info(result)
        self.assertIn(self.constant.STOP_SUCCESS_MSG, result,
                      "执行失败" + step_txt)

        step_txt = '----step3:备节点注入60s句柄耗尽故障; expect:成功----'
        self.log.info(step_txt)
        session = ComThread(self.com.cfe_inject,
                            args=(self.pri_root,
                                  self.inject_cmd))
        session.setDaemon(True)
        session.start()
        self.start_time = time.time()

        step_txt = '----step4:主节点上执行gs_om start  expect:失败----'
        self.log.info(step_txt)
        result = self.pri_sh.startDbCluster(get_detail=True)
        self.log.info(result)
        self.assertIn(self.constant.TOO_MANYY_FILE_MSG, result,
                      "执行失败" + step_txt)
        self.assertNotIn(self.constant.START_SUCCESS_MSG, result,
                         "执行失败" + step_txt)

        self.log.info("-----注入故障结果-----")
        session.join(60)
        result = session.get_result()
        self.log.info(result)
        self.assertIn(self.constant.SUCCESS_CFE_FULL_FILENUM_MSG, result,
                      "执行失败" + step_txt)
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.pri_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                time.sleep(5)
                break

        step_txt = '----step4:故障清理后主节点上执行gs_om start  expect:成功----'
        self.log.info(step_txt)
        result = self.pri_sh.startDbCluster(get_detail=True)
        self.log.info(result)
        self.assertNotIn(self.constant.TOO_MANYY_FILE_MSG, result,
                         "执行失败" + step_txt)
        self.assertIn(self.constant.START_SUCCESS_MSG, result,
                      "执行失败" + step_txt)

    def tearDown(self):
        self.log.info("----this is tearDown----")
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.pri_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                break
        step_txt = '----集群状态异常时，恢复环境----'
        self.log.info(step_txt)
        status = self.pri_sh.getDbClusterStatus("status")
        if not status:
            self.result = self.pri_sh.startDbCluster()
            self.final_status = self.pri_sh.getDbClusterStatus("status")
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
        if not status:
            self.assertIn(self.constant.START_SUCCESS_MSG, self.result,
                          "执行失败" + step_txt)
            self.assertTrue(self.final_status, "执行失败" + step_txt)
